/***************************************************************************************************
 *Copyright(C),2010-2017,Sumscope
 *FileName	:  pinyin_search_idvec.h
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2017/06/04
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/
#pragma once

#include "../../core.h"
#include "pinyin_search_define.h"
#include "pinyin_search_set.h"

namespace qb {
namespace base {

namespace internal {
class IndexIdStore;
class S_CORE_EXPORT IndexIdVec {
  typedef unsigned int uint;
  typedef uint KeyType;
  typedef uint CountType;
  typedef IndexIdVec Base;
  IndexId* m_first;  // 按照bid递增
  int m_count;       // 个数
  int m_capcity;     // 容量
                     // IndexIdStore*	m_store;
 public:
  class const_iterator {
    int m_index;
    const Base* m_owner;

   public:
    KeyType first;
    CountType second;

   public:
    explicit const_iterator(const Base* owner, int index) {
      m_owner = owner;
      m_index = index;
      owner->get(index, first, second);
    }
    const_iterator(const const_iterator& it)
        : m_owner(it.m_owner),
          m_index(it.m_index),
          first(it.first),
          second(it.second) {}
    const_iterator& operator++() {
      m_index++;
      m_owner->get(m_index, first, second);
      return *this;
    }
    bool operator!=(const const_iterator& ci) const {
      return m_owner != ci.m_owner || m_index != ci.m_index;
    }
    const_iterator* operator->() { return this; }
  };

 public:
  IndexIdVec();
  IndexIdVec(IndexId* first, int count, int capcity);

  void bind(IndexId* first, int count, int capcity);
  void copyfrom(const IndexIdVec& iivec);
  void copyfrom(const InverseSet& iset);
  void copyto(InverseSet& iset);
  bool equal(const InverseSet& iset) const;
  ~IndexIdVec();
  int size() const { return m_count; }
  IndexId at(int i) const { return m_first[i]; }
  bool add(int key);
  void remove(int key);
  bool exist(int key) const;
  void clear();
  void intersect(const InverseSet& iset);
  void intersect(const IndexIdVec& iis);
  void intersect_old(const IndexIdVec& iis);
  bool empty() const { return m_count <= 0; }
  const IndexId* first() const { return m_first; }
  int count() const { return m_count; }
  void transform();

  bool get(int index, KeyType& key, CountType& val) const;
  const_iterator cbegin() const { return const_iterator(this, 0); }
  const_iterator cend() const { return const_iterator(this, m_count); }

 protected:
  inline int find_fast(int key, int npos) const {
    if (npos < 0 || m_first == nullptr || npos >= m_count) return m_count;
    if (key <= spell::getkey(m_first[npos])) return npos;
    if (m_count >= 1) {
      int last = spell::getkey(m_first[m_count - 1]);
      if (key > last) return m_count;
      if (key == last) return m_count - 1;
    }
    return -1;
  }
  int find_slow(int key, int npos) const;
  int find(int key) const;
  int find_after(int key, int npos) const;
  int find_slow2(int key, int npos) const;
  int find_after_old(int key, int npos) const;
  void check();
};

}  // namespace internal
}  // namespace base
}  // namespace qb
